<?php

declare(strict_types=1);

namespace App\Service;

use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;

class DbService
{
    #[Inject]
    protected static Db $db;

    /**
     *  ON DUPLICATE KEY UPDATE 封装
     *  @param string $tableName 表名
     *  @param array  $columns 所有列
     *  @param array  $update_keys 如果存在，要进行修改的字段
     *  @param array  $data  值
     *  @return boolean 返回执行结果
     */
    public static function saveOrUpdate(string $table_name, array $columns, array $update_keys, array $data = []): bool
    {
        // 获取当前模型表名
        if (empty($table_name)) throw new \Exception('缺少数据库表名');
        if (empty($columns)) throw new \Exception('缺少数据库字段');
        if (empty($update_keys)) throw new \Exception('缺少要修改的字段');
        
        $column_list = [];
        $value_strs  = [];
        $update_strs = [];
        
        foreach ($columns as $operate => $column) {
            array_push($column_list, $column);
            
            if (in_array($column, $update_keys)) {
                switch (strtolower((string)$operate)) {
                    case 'inc': array_push($update_strs, sprintf('%s = %s + VALUES(%s)', $column, $column, $column)); break;
                    case 'dec': array_push($update_strs, sprintf('%s = %s - VALUES(%s)', $column, $column, $column)); break;
                    default: array_push($update_strs, sprintf('%s = VALUES(%s)', $column, $column)); break;
                }
            }
        }
        
        foreach ($data as $row) array_push($value_strs, sprintf('"%s"', implode('", "', $row)));
        
        $columns_str = '`' . implode('`, `', $column_list) . '`';
        $values_str  = '(' . implode('), (', $value_strs) . ')';
        $updates_str = implode(', ', $update_strs);
        
        $sql = sprintf(
            'INSERT INTO %s (%s) VALUES %s ON DUPLICATE KEY UPDATE %s',
            $table_name, $columns_str, $values_str, $updates_str
        );

        return self::$db->query($sql) !== false;
    }
}
